package com.atguigu.spzx.cloud.order.service.impl;

import com.atguigu.spzx.cloud.order.entity.Order;
import com.atguigu.spzx.cloud.order.feign.UserFeignClient;
import com.atguigu.spzx.cloud.order.mapper.OrderMapper;
import com.atguigu.spzx.cloud.order.service.OrderService;
import com.atguigu.spzx.cloud.user.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Random;

/**
 * projectName: com.atguigu.spzx.cloud.order.service.impl
 *
 * @author: 顾司羽
 * time: 2024/12/24 11:32 周二
 * description:
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    //nacos的api代码! 可以进行服务拉取
    //@Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private UserFeignClient userFeignClient;


// TODO: 1、========================== 使用RestTemplate地址直接访问 ======================================================
    /*// com.atguigu.spzx.cloud.order.service.impl;
    //@Service
    public class OrderServiceImpl使用RestTemplate地址直接访问 implements OrderService {

    //@Autowired
    private OrderMapper orderMapper ;

    //@Autowired
    private RestTemplate restTemplate;

    @Override
    public Order findOrderByOrderId(Long orderId) {
        Order order = orderMapper.findOrderByOrderId(orderId);
        if (order == null) {
            return null;
        }
        //服务之间的远程调用
        User user =  restTemplate.getForObject("http://localhost:10100/api/user/findUserByUserId/"+order.getUserId(),
                User.class);
        //数据整合
        order.setUser(user);
        return order;
    }*/

// TODO: 2、========================== 使用nacos和自定义负载均衡算法 ======================================================
/* //todo  * 注册中心拉取服务列表
  //todo  * 自定义负载均衡算法
  //todo  * restTemplate远程调用

    @Override
    public Order findOrderByOrderId(Long orderId) {
        Order order = orderMapper.findOrderByOrderId(orderId);
        if (order == null) {
            return null;
        }

        //1. 拉取指定名称的服务列表
        /**
         * 参数: string,要拉取的服务名 (对方的spring.application.name)
         * 返回值: 服务名对应注册中心中的`活跃`服务实例集合 <ServiceInstance> -> 服务实例信息的实体类(服务具体的ip port...)

        List<ServiceInstance> instances = discoveryClient.getInstances("spzx-cloud-user");

        //2.负载均衡(轮询,随机,权重)
        int index = new Random().nextInt(instances.size()); //[0-size-1]
        ServiceInstance serviceInstance = instances.get(index);

        //3.获取选中实例信息(ip / port -> url)
        String host = serviceInstance.getHost();
        int port = serviceInstance.getPort();
        String url = "http://"+host+":"+port+"/api/user/findUserByUserId/"+order.getUserId();

        //4.使用restTemplate进行远程访问
        User user = restTemplate.getForObject(url, User.class);

        //5.结果整合
        order.setUser(user);

        return order;
    }*/

// TODO: 3、========================== 使用nacos和 loadbalancer负载均衡算法  Nacos + loadbalancer + restTemplate ======================================================
    /*// com.atguigu.spzx.cloud.order.service.impl;


     *  Nacos + loadbalancer + restTemplate
     *
     * restTemplate 不用导依赖 spring自带的
     *  1.导入依赖 (nacos | loadbalancer)
     *  2.配置了RestTemplate
     *  3.开启负载均衡 @LoadBalanced
     *  4.restTemplate进行访问了

    @Service
    public class OrderServiceImpl implements OrderService {

        @Autowired
        private OrderMapper orderMapper ;
        @Autowired
        private RestTemplate restTemplate;

        @Override
        public Order findOrderByOrderId(Long orderId) {
            Order order = orderMapper.findOrderByOrderId(orderId);
            if (order == null) {
                return null;
            }
            // hostL:port -> 对方的服务名
            User user = restTemplate.getForObject("http://spzx-cloud-user/api/user/findUserByUserId/"+order.getUserId(), User.class);
            order.setUser(user);
            return order;
        }*/

// TODO: 4、========================== 使用nacos和 loadbalancer负载均衡算法  Nacos + loadbalancer + FeignClient(value="服务的名 默认开启负载均衡") ======================================================
    /*// com.atguigu.spzx.cloud.order.service.impl;

     *
     *  1.谁调谁导入OpenFeign的依赖
     *  2.开启Feign客户端
     *  3.{在UserFeignClient里}把对方的Controller层变成OpenFeign客户端
     *  4. userFeignClient进行访问了

    @Service
    public class OrderServiceImpl implements OrderService {
        @Autowired
        private OrderMapper orderMapper ;

        @Autowired
        private UserFeignClient userFeignClient;

        @Override
        public Order findOrderByOrderId(Long orderId) {
            Order order = orderMapper.findOrderByOrderId(orderId);
            if (order == null) {
                return null;
            }
            //以前一样,方法调用
            User user = userFeignClient.findUserById(order.getUserId());
            order.setUser(user);
            return order;
        }*/

    @Override
    public Order findOrderByOrderId(Long orderId) {

    // TODO: 2024/12/24
    //  调用用户微服务(controller中有4中请求方式)
        // 根据订单id查询订单详情 里面包含了userId
        Order order = orderMapper.findOrderByOrderId(orderId);
        // 判断订单详情是否为空
        if (order == null) {
            return null;
        }
        //从订单详情中取出userId作为远程调用的接口的参数
        Long userId = order.getUserId();
// TODO:  传统方式 使用RestTemplate地址直接访问
 /*     // 通过restTemplate发送远程调用           协议+ip:端口号/接口路径/参数
        User user = restTemplate.getForObject("http://localhost:10100/api/user/findUserByUserId/" + userId, User.class);*/
// TODO:  nacos的注册中心远程调用  通过服务名，找到对应服务的ip和端口。 解耦
        //不知道ip和端口号，在nacos注册中心里，只能拿到服务名，（底层还是通过服务名找到ip和端口号）
  /*    User user = restTemplate.getForObject("http://spzx-cloud-user/api/user/findUserByUserId/"+ userId, User.class);*/
// TODO:  feign远程调用 (以调用方法的形式，去获取必要的数据。 OpenFeign帮助我们转换请求的URL)
        User user = userFeignClient.findUserByUserId(userId);
        //设置用户信息
        order.setUser(user);
        //返回
        return order;
    }

    @Override
    public List<Order> findOrderList(Long userId) {
        return orderMapper.selectList(userId);
    }
}
